﻿// Copyright (c) 2015, Microsoft Corporation
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
// IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//

using System;
using System.Threading;

namespace MyLivingRoom.Core
{
    public class DisposeActionScope : IDisposable
    {
        #region Instance Fields
        private volatile Action _disposeAction;
        #endregion Instance Fields

        #region Constructors / Finalizer
        public DisposeActionScope(Action initializeAction, Action disposeAction)
            : this(disposeAction)
        {
            ValidateArgument.IsNotNull(initializeAction, nameof(initializeAction));
            initializeAction();
        }

        public DisposeActionScope(Action disposeAction)
        {
            ValidateArgument.IsNotNull(disposeAction, nameof(disposeAction));
            _disposeAction = disposeAction;
        }

        ~DisposeActionScope()
        {
            this.Dispose(false);
        }
        #endregion Constructors / Finalizer

        #region IDisposable Members
        public void Dispose()
        {
            this.Dispose(true);
        }
        #endregion IDisposable Members

        #region Private Implementation

        private void Dispose(bool suppressFinalize)
        {
            var disposeAction = Interlocked.Exchange(ref _disposeAction, null);
            if (disposeAction != null)
                disposeAction();

            if (suppressFinalize)
                GC.SuppressFinalize(this);
        }

        #endregion Private Implementation
    }
}
